﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WinCustControls
{
    public partial class UPanel : Panel
    {
        public UPanel()
        {
            InitializeComponent();
            SetStyle(ControlStyles.AllPaintingInWmPaint, true); // 忽略窗口消息，减少闪烁
            SetStyle(ControlStyles.OptimizedDoubleBuffer, true);// 绘制到缓冲区，减少闪烁
            SetStyle(ControlStyles.UserPaint, true);// 控件由其自身而不是操作系统绘制
            SetStyle(ControlStyles.ResizeRedraw, true);// 控件在调整其大小时重绘
            SetStyle(ControlStyles.SupportsTransparentBackColor, true);// 控件支持透明背景

            r = this.ClientRectangle;
        }

        private Color _bgColor = Color.LightGray;
        /// <summary>
        /// 背景色1（渐变颜色1）
        /// </summary>
        [DefaultValue(typeof(Color), "LightGray"), Description("控件的背景色1")]
        public Color BgColor
        {
            get { return _bgColor; }
            set
            {
                _bgColor = value;
                //Refresh(); // 强制重绘，立即执行
                //（推荐）因为我们往往更倾向在多个控件的值更改后一起重绘
                Invalidate(); // 引发重绘，不会立即执行
            }
        }

        private Color _bgColor2 = Color.Transparent;
        /// <summary>
        /// 背景色2（渐变颜色2）
        /// </summary>
        [DefaultValue(typeof(Color), "Transparent"), Description("控件的背景色2")]
        public Color BgColor2
        {
            get { return _bgColor2; }
            set
            {
                _bgColor2 = value;
                Invalidate(); // 重绘
            }
        }

        private Color _borderColor = Color.Gray;
        /// <summary>
        /// 边框颜色
        /// </summary>
        [DefaultValue(typeof(Color), "Gray"), Description("控件的边框颜色")]
        public Color BorderColor
        {
            get { return _borderColor; }
            set
            {
                _borderColor = value;
                Invalidate(); // 重绘
            }
        }

        private int _borderWidth = 0;
        /// <summary>
        /// 边框粗细
        /// </summary>
        [DefaultValue(typeof(int), "0"), Description("控件的边框粗细")]
        public int BorderWidth
        {
            get { return _borderWidth; }
            set
            {
                _borderWidth = value;
                Invalidate(); // 重绘
            }
        }

        private int _radius = 5;
        /// <summary>
        /// 边框圆角半径
        /// </summary>
        [DefaultValue(typeof(int), "5"), Description("控件的边框圆角半径")]
        public int Radius
        {
            get { return _radius; }
            set
            {
                _radius = value;
                Invalidate(); // 重绘
            }
        }

        private LinearGradientMode _gradientMode = LinearGradientMode.Vertical;
        /// <summary>
        /// 背景渐变模式
        /// </summary>
        [DefaultValue(typeof(LinearGradientMode), "Vertical"), Description("控件的背景渐变模式")]
        public LinearGradientMode GradientMode
        {
            get { return _gradientMode; }
            set
            {
                _gradientMode = value;
                Invalidate(); // 重绘
            }
        }


        /// <summary>
        /// 绘制区域
        /// </summary>
        Rectangle r;

        /// <summary>
        /// 重设控件区域
        /// </summary>
        /// <param name="e"></param>
        protected override void OnSizeChanged(EventArgs e)
        {
            base.OnSizeChanged(e);

            r = this.ClientRectangle;

            this.Region = new Region(r);
            r.Width -= 1;
            r.Height -= 1;
        }

        /// <summary>
        /// 重写绘制事件
        /// </summary>
        /// <param name="e"></param>
        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);

            // 绘制工作：边框、背景...
            Graphics g = e.Graphics;
            // 设置绘图呈现质量
            g.SmoothingMode = SmoothingMode.AntiAlias;
            // 边框圆角矩形
            GraphicsPath borderPath = new GraphicsPath();
            // 背景圆角矩形
            GraphicsPath bgPath = new GraphicsPath();
            // 内部填充矩形
            Rectangle rect;

            if (_radius > 0)
            {
                // 生成外部矩形的圆角矩形路径
                borderPath = PaintClass.GetRoundRectangle(r, _radius);

                if (_borderWidth > 0)
                {
                    // 填充边框矩形
                    g.FillPath(new SolidBrush(_borderColor), borderPath);
                    // 定义内部矩形结构
                    rect = new Rectangle(r.X + _borderWidth, r.Y + _borderWidth, r.Width - 2 * _borderWidth, r.Height - 2 * _borderWidth);
                    // 生成内部矩形路径
                    bgPath = PaintClass.GetRoundRectangle(rect, _radius - 1);
                }
                else
                {
                    bgPath = borderPath;
                    rect = r;
                }

                if (_bgColor2 != Color.Transparent)
                {
                    // 渐变画刷
                    LinearGradientBrush bgBrush = new LinearGradientBrush(rect, _bgColor, _bgColor2, _gradientMode);
                    // 填充背景
                    g.FillPath(bgBrush, bgPath);
                }
                else
                {
                    Brush b = new SolidBrush(_bgColor);
                    g.FillPath(b, bgPath);
                }
            }
            else
            {
                if (_borderWidth > 0)
                {
                    // 填充边框矩形
                    g.FillRectangle(new SolidBrush(_borderColor), r);
                    // 定义内部矩形结构
                    rect = new Rectangle(r.X + _borderWidth, r.Y + _borderWidth, r.Width - 2 * _borderWidth, r.Height - 2 * _borderWidth);
                }
                else
                {
                    // bgPath = borderPath;
                    rect = r;
                }

                if (_bgColor2 != Color.Transparent)
                {
                    // 渐变画刷
                    LinearGradientBrush bgBrush = new LinearGradientBrush(rect, _bgColor, _bgColor2, _gradientMode);
                    // 填充背景
                    g.FillRectangle(bgBrush, rect);
                }
                else
                {
                    Brush b = new SolidBrush(_bgColor);
                    g.FillRectangle(b, rect);
                }
            }
        }
    }
}
